package authenticate;

import Base.ResourceTest;
import EntityBuilder.RenterBuilder;
import com.huawei.translate.api.AuthenticateApi;
import com.huawei.translate.model.AccessToken;
import com.huawei.translate.model.Renter;
import com.huawei.translate.provider.MSTranslateProvider;
import com.huawei.translate.utils.SystemConfig;
import com.huawei.translate.vo.AccessTokenGenerateRequest;
import com.huawei.translate.vo.AccessTokenResponse;
import com.huawei.translate.vo.PermissionRequest;
import com.huawei.translate.vo.PermissionResponse;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.UUID;

import static org.mockito.Mockito.doReturn;

@RunWith(SpringRunner.class)
public class When_user_authenticate extends ResourceTest {

    private Renter renter;

    @Autowired
    @Mock
    private MSTranslateProvider msTranslateProvider;

    @Autowired
    @InjectMocks
    private AuthenticateApi authenticateApi;

    @Before
    public void setup() {
        renter = new RenterBuilder(renterRepository).WithAppSecret(UUID.randomUUID().toString()).Build();
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void should_response_ms_speech_access_token_when_user_request_speech() {

        doReturn("Accesstoken").when(msTranslateProvider).getSpeechAccessToken();

        AccessTokenGenerateRequest request = new AccessTokenGenerateRequest(renter.getAppSecret(), "secret");

        ResponseEntity<AccessTokenResponse> responseEntity = sendGenerateSpeechAccessTokenRequest(request);

        AccessTokenResponse response = responseEntity.getBody();

        Assert.assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
        Assert.assertEquals(HttpStatus.OK.value(), response.getCode());
        Assert.assertEquals(SystemConfig.getProperty("microsoft.expiredDuration"), response.getExpireDuration());
        Assert.assertNotNull(response.getAccessToken());
    }

    @Test
    public void should_response_access_token_when_user_request_accessToken() {

        AccessTokenGenerateRequest request = new AccessTokenGenerateRequest(renter.getAppSecret(), "secret");
        ResponseEntity<AccessTokenResponse> responseEntity = sendGenerateAccessTokenRequest(request);

        AccessTokenResponse response = responseEntity.getBody();

        AccessToken token = accessTokenRepository.findByAppSecret(request.getAppSecret());

        Assert.assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
        Assert.assertEquals(HttpStatus.OK.value(), response.getCode());
        Assert.assertEquals(SystemConfig.getProperty("expiredDuration"), response.getExpireDuration());
        Assert.assertNotNull(token);
    }

    @Test
    public void should_response_bad_request_when_user_request_invalid() {
        AccessTokenGenerateRequest request = new AccessTokenGenerateRequest("", "secret");
        ResponseEntity<AccessTokenResponse> responseEntity = sendGenerateAccessTokenRequest(request);

        Assert.assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
        Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), responseEntity.getBody().getCode());
    }

    @Test
    public void should_response_forbidden_when_user_not_exist() {
        AccessTokenGenerateRequest request = new AccessTokenGenerateRequest("userNotExist", "secret");

        ResponseEntity<AccessTokenResponse> responseEntity = sendGenerateAccessTokenRequest(request);

        Assert.assertEquals(HttpStatus.FORBIDDEN.value(), responseEntity.getBody().getCode());
    }

    @Test
    public void should_return_app_secret_when_user_apply_permission() {
        PermissionRequest request = new PermissionRequest();
        request.setAppKey("HuaWei");
        request.setAppName("Test");
        ResponseEntity<PermissionResponse> responseEntity =
                testRestTemplate.postForEntity("/api/oauth", request, PermissionResponse.class);

        PermissionResponse response = responseEntity.getBody();

        Renter renter = renterRepository.findByAppSecret(response.getAppSecret());

        Assert.assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
        Assert.assertEquals(renter.getAppSecret(), response.getAppSecret());
    }

    private ResponseEntity<AccessTokenResponse> sendGenerateAccessTokenRequest(AccessTokenGenerateRequest request) {
        return testRestTemplate.postForEntity("/api/oauth/generate", request, AccessTokenResponse.class);
    }

    private ResponseEntity<AccessTokenResponse> sendGenerateSpeechAccessTokenRequest(AccessTokenGenerateRequest request) {
        return testRestTemplate.postForEntity("/api/oauth/generate/speech", request, AccessTokenResponse.class);
    }
}
